//
//  YCMediator.swift
//  YCMediator
//
//  Created by YC on 2017/2/28.
//  Copyright © 2017年 YC. All rights reserved. mail:yangchong364@qq.com
//

import UIKit

class YCMediator: NSObject {
    static let shared = YCMediator()
    
    var cachedTarget = [String : NSObject!]()
    
    private override init(){
    }
    
    // 远程App调用入口
    open func performAction(with url: URL!, completion: (([AnyHashable : Any]?) -> Swift.Void)!) -> Any! {
        var params = [String : String]()
        
        if let urlString = url.query {
            for param in urlString.components(separatedBy: "&") {
                
                let elts = param.components(separatedBy: "=")
                if elts.count < 2 {
                    continue
                }
                
                params[elts.first!] = elts.last!
                
            }
        }
        
        // 这里这么写主要是出于安全考虑，防止黑客通过远程方式调用本地模块。这里的做法足以应对绝大多数场景，如果要求更加严苛，也可以做更加复杂的安全逻辑。
        let actionName = url.path.replacingOccurrences(of: "/", with: "")
        if actionName.hasPrefix("native") {
            return false
        }
        
        // 这个demo针对URL的路由处理非常简单，就只是取对应的target名字和method名字，但这已经足以应对绝大部份需求。如果需要拓展，可以在这个方法调用之前加入完整的路由逻辑
        let result = self.performTarget(url.host!, action: actionName, params: params, shouldCacheTarget: false)
        
        
        if completion != nil {
            if result != nil{
                completion(["result":result as Any])
            }else {
                completion(nil)
            }
        }
        
        return result;
    }
    
    // 本地组件调用入口
    open func performTarget(_ targetName: String, action actionName: String, params: [String : Any]!, shouldCacheTarget: Bool) -> Any!{
        
        let targetClassString = "Target_\(targetName)"
        let actionString = "Action_\(actionName):"
        
        var target = self.cachedTarget[targetClassString]
        
        if target == nil {
            var module = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
            module = module.replacingOccurrences(of: "-", with: "_")
            let targetClass = NSClassFromString(module + "." + targetClassString) as! NSObject.Type
            target = targetClass.init()
        }
        
        let action = NSSelectorFromString(actionString)
        
        if target == nil {
            // 这里是处理无响应请求的地方之一，这个demo做得比较简单，如果没有可以响应的target，就直接return了。实际开发过程中是可以事先给一个固定的target专门用于在这个时候顶上，然后处理这种请求的
            return nil;
        }
        
        if (shouldCacheTarget) {
            self.cachedTarget[targetClassString] = target;
        }
        
        if target!.responds(to: action) {
            return target!.perform(action, with: params).takeUnretainedValue()
        }else {
            // 这里是处理无响应请求的地方，如果无响应，则尝试调用对应target的notFound方法统一处理
            let action = NSSelectorFromString("notFound:")
            
            if target!.responds(to: action) {
                return target!.perform(action, with: params)
            }else {
                // 这里也是处理无响应请求的地方，在notFound都没有的时候，这个demo是直接return了。实际开发过程中，可以用前面提到的固定的target顶上的。
                self.cachedTarget.removeValue(forKey: targetClassString)
                
                return nil;
            }
            
        }
    }
    
    open func releaseCachedTargetWithTargetName(_ targetName:String) -> Void {
        let targetClassString = "Target_\(targetName)"
        self.cachedTarget.removeValue(forKey: targetClassString)
    }
    
}
